revision:
<div class="grid-container" id="grid" onclick='changeColor()'></div> <style> .grid-container{display: grid; width: 50%; height: 100%; grid-template-columns: repeat(12, 3vw); grid-template-rows: repeat(12, 3vw); gap: 1vw; background-color: lightblue; box-shadow: 1vw 1vw 1vw lightgreen;} .grid-item {background-color: blue; border-style: solid; border-width: 0.5vw; border-color: red; } </style> <script> const grid = document.getElementById("grid"); for(let i = 1; i < 13; i++) { for(let x = 1; x < 13; x++){ var item = document.createElement("div"); item.setAttribute("style", "grid-area:" + i + " / " + x + " / " + i + " / " + x); item.setAttribute("grid-column", x + " / span 1"); item.setAttribute("grid-row", i + " / span 1"); item.setAttribute("class", "grid-item"); grid.appendChild(item); } } function changeColor(){ var currDiv = document.getElementById("grid"); currDiv.style.backgroundColor = "green"; } </script>
- Tear the cloth with your mouse
- Right click and drag to cut
code: <div> <canvas id="c"></canvas> <div id="info"> <div id="top"> <a id="close" href="">×</a> </div> <p> <br>- Tear the cloth with your mouse <br> <br>- Right click and drag to cut <br> <div class="center"></div> </p> </div> </div> <style> #c{display: block; margin: 2vw auto 0; } #info {position: relative; left: -1vw; top: -1vw; width: auto;max-width: 20vw; height: 8vw; background: skyblue; border-bottom-right-radius: 1vw; border: 0.1vw solid #ccc;} #top {background: green; width: 100%; height: auto; position: relative; border-bottom: 0.1vw solid #eee;} p {font-family: Arial, sans-serif; color: black; text-align: justify; font-size: 1vw; margin: 0vw 1vw;} .center {text-align: center;} #net {text-align:center;white-space:nowrap; font-size:1.9vw; background:rgba(0,0,0,0.1); padding:0.8vw 1.2vw;border-radius:0.8vw; display:block; color:#888;} #net > span {color:#3377ee; font-family: Helvetica, Arial, sans-serif; font-size: 1.4vw;display: block; margin: 0 auto; text-align: center; text-decoration:none; } a {font-family: sans-serif;color: #444; text-decoration: none;font-size: 2vw;} #site {float: left; margin: 1vw; color: #ff9900; border-bottom: .1vw dashed #ccc; padding-bottom: .3vw;} #site:hover {color: #ffaa11;} #close {float: right; margin: 1vw;} #p {font-family: Verdana, sans-serif; position: absolute; right: 1vw; bottom: 1vw; color: #4099ff; border: .1vw dashed #4099ff; padding: .4vw .8vw;} #new {width: 100%; text-align: center; font-size: 1.8vw; font-family: Helvetica; margin-top: 1.2vw;} #new a {font-size: 2vw; color: #4099ff;} .bull {opacity: 0.3; margin: 0 .6vw; font-size: 1.4vw;} </style> <script> document.getElementById('close').onmousedown = function(e) { e.preventDefault(); document.getElementById('info').style.display = 'none'; return false; }; // settings var physics_accuracy = 3, mouse_influence = 20, mouse_cut = 5, gravity = 1200, cloth_height = 30, cloth_width = 80, start_y = 20, spacing = 7, tear_distance = 60; window.requestAnimFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); }; var canvas, ctx, cloth, boundsx, boundsy, mouse = { down: false, button: 1, x: 0, y: 0, px: 0, py: 0 }; var Point = function (x, y) { this.x = x; this.y = y; this.px = x; this.py = y; this.vx = 0; this.vy = 0; this.pin_x = null; this.pin_y = null; this.constraints = []; }; Point.prototype.update = function (delta) { if (mouse.down) { var diff_x = this.x - mouse.x, diff_y = this.y - mouse.y, dist = Math.sqrt(diff_x * diff_x + diff_y * diff_y); if (mouse.button == 1) { if (dist < mouse_influence) { this.px = this.x - (mouse.x - mouse.px) * 1.8; this.py = this.y - (mouse.y - mouse.py) * 1.8; } } else if (dist < mouse_cut) this.constraints = []; } this.add_force(0, gravity); delta *= delta; nx = this.x + ((this.x - this.px) * .99) + ((this.vx / 2) * delta); ny = this.y + ((this.y - this.py) * .99) + ((this.vy / 2) * delta); this.px = this.x; this.py = this.y; this.x = nx; this.y = ny; this.vy = this.vx = 0 }; Point.prototype.draw = function () { if (!this.constraints.length) return; var i = this.constraints.length; while (i--) this.constraints[i].draw(); }; Point.prototype.resolve_constraints = function () { if (this.pin_x != null && this.pin_y != null) { this.x = this.pin_x; this.y = this.pin_y; return; } var i = this.constraints.length; while (i--) this.constraints[i].resolve(); this.x > boundsx ? this.x = 2 * boundsx - this.x : 1 > this.x && (this.x = 2 - this.x); this.y < 1 ? this.y = 2 - this.y : this.y > boundsy && (this.y = 2 * boundsy - this.y); }; Point.prototype.attach = function (point) { this.constraints.push( new Constraint(this, point) ); }; Point.prototype.remove_constraint = function (constraint) { this.constraints.splice(this.constraints.indexOf(constraint), 1); }; Point.prototype.add_force = function (x, y) { this.vx += x; this.vy += y; var round = 400; this.vx = ~~(this.vx * round) / round; this.vy = ~~(this.vy * round) / round; }; Point.prototype.pin = function (pinx, piny) { this.pin_x = pinx; this.pin_y = piny; }; var Constraint = function (p1, p2) { this.p1 = p1; this.p2 = p2; this.length = spacing; }; Constraint.prototype.resolve = function () { var diff_x = this.p1.x - this.p2.x, diff_y = this.p1.y - this.p2.y, dist = Math.sqrt(diff_x * diff_x + diff_y * diff_y), diff = (this.length - dist) / dist; if (dist > tear_distance) this.p1.remove_constraint(this); var px = diff_x * diff * 0.5; var py = diff_y * diff * 0.5; this.p1.x += px; this.p1.y += py; this.p2.x -= px; this.p2.y -= py; }; Constraint.prototype.draw = function () { ctx.moveTo(this.p1.x, this.p1.y); ctx.lineTo(this.p2.x, this.p2.y); }; var Cloth = function () { this.points = []; var start_x = canvas.width / 2 - cloth_width * spacing / 2; for (var y = 0; y <= cloth_height; y++) { for (var x = 0; x <= cloth_width; x++) { var p = new Point(start_x + x * spacing, start_y + y * spacing); x != 0 && p.attach(this.points[this.points.length - 1]); y == 0 && p.pin(p.x, p.y); y != 0 && p.attach(this.points[x + (y - 1) * (cloth_width + 1)]) this.points.push(p); } } }; Cloth.prototype.update = function () { var i = physics_accuracy; while (i--) { var p = this.points.length; while (p--) this.points[p].resolve_constraints(); } i = this.points.length; while (i--) this.points[i].update(.016); }; Cloth.prototype.draw = function () { ctx.beginPath(); var i = cloth.points.length; while (i--) cloth.points[i].draw(); ctx.stroke(); }; function update() { ctx.clearRect(0, 0, canvas.width, canvas.height); cloth.update(); cloth.draw(); requestAnimFrame(update); } function start() { canvas.onmousedown = function (e) { mouse.button = e.which; mouse.px = mouse.x; mouse.py = mouse.y; var rect = canvas.getBoundingClientRect(); mouse.x = e.clientX - rect.left, mouse.y = e.clientY - rect.top, mouse.down = true; e.preventDefault(); }; canvas.onmouseup = function (e) { mouse.down = false; e.preventDefault(); }; canvas.onmousemove = function (e) { mouse.px = mouse.x; mouse.py = mouse.y; var rect = canvas.getBoundingClientRect(); mouse.x = e.clientX - rect.left, mouse.y = e.clientY - rect.top, e.preventDefault(); }; canvas.oncontextmenu = function (e) { e.preventDefault(); }; boundsx = canvas.width - 1; boundsy = canvas.height - 1; ctx.strokeStyle = '#888'; cloth = new Cloth(); update(); } window.onload = function () { canvas = document.getElementById('c'); ctx = canvas.getContext('2d'); canvas.width = 560; canvas.height = 350; start(); }; </script>